package cn.backpackerxl.easyJDBC.util;

import java.lang.reflect.Field;
import java.util.*;

public final class AddStringRule implements JSONParseRule {
    private boolean isArray;
    private boolean isList;
    private boolean isMap;

    @Override
    public boolean evaluate(JSONExpression jsonExpression) {
        boolean eval = false;
        Field field = jsonExpression.getField();
        this.isArray = field.getType().getTypeName().equals("java.lang.String[]");
        this.isList = jsonExpression.getTypeName().equals("java.util.List<java.lang.String>");
        this.isMap = jsonExpression.getTypeName().equals("java.util.Map<java.lang.String, java.lang.String>");
        if (jsonExpression.getTypeof() == Typeof.STRING || this.isArray || this.isList || this.isMap) {
            this.apply(jsonExpression.getObject(), jsonExpression.getField(), jsonExpression.getJsonObject());
            eval = true;
        }
        return eval;
    }

    @Override
    public void apply(Object entity, Field field, JSONObject obj) {
        try {
            if (this.isArray) {
                Object[] objects = obj.getArrays().stream().map(JSONObject::getStrValue).toArray();
                String[] strings = Arrays.copyOf(objects, objects.length, String[].class);
                field.set(entity, strings);
            } else if (this.isList) {
                List<String> list = new ArrayList<>();
                this.applyList(obj, list);
                field.set(entity, list);
            } else if (this.isMap) {
                Map<String, String> map = new HashMap<>();
                this.applyMap(obj, map);
                field.set(entity, map);
            } else {
                field.set(entity, obj.getStrValue());
            }
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }

    private void applyList(JSONObject obj, List<String> list) {
        for (JSONObject jsonObject : obj.getArrays()) {
            list.add(jsonObject.getStrValue());
        }
    }

    private void applyMap(JSONObject obj, Map<String, String> map) {
        for (JSONObject object : obj.getArrays()) {
            for (String s : object.getObjValue().keySet()) {
                map.put(s, object.getObjValue().get(s).getStrValue());
            }
        }
    }
}
